# -*- coding: utf-8 -*-
from MyApi import *
import thosttraderapi as api
import os
import configparser

#local config check check
if(os.path.exists("config.local.ini")):
	configfile = "config.local.ini"
else:
	configfile = "config.ini"


configins=configparser.ConfigParser()
configins.read(configfile)

#Rtnctl
INSTRSTATUS=configins['Rtnctl']['instrstatus']


class CTradeSpi(api.CThostFtdcTraderSpi):
	myapi=''
	def __init__(self,myapi):
		api.CThostFtdcTraderSpi.__init__(self)
		self.myapi=myapi
		
	def OnFrontConnected(self) -> "void":
		print("receive OnFrontConnected")
		self.myapi.ctlevent.set()

	def OnRspAuthenticate(self, pRspAuthenticateField: 'CThostFtdcRspAuthenticateField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":	
		PrintReName("OnRspAuthenticate")
		if(pRspInfo.ErrorID == 0):
			PrintReMsg(pRspInfo)
			self.myapi.ctlevent.set()
		else:
			PrintReMsg(pRspInfo)
			os._exit(233)
		
	def OnRspUserLogin(self, pRspUserLogin: 'CThostFtdcRspUserLoginField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		PrintReName("OnRspUserLogin")
		if(pRspInfo.ErrorID == 0):
			PrintReMsg(pRspInfo)
			self.myapi.ctlevent.set()
		else:
			PrintReMsg(pRspInfo)
			os._exit(233)
		
	def OnRspQryTradingAccount(self, pTradingAccount: 'CThostFtdcTradingAccountField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		currlist=[pTradingAccount.BrokerID,\
			pTradingAccount.AccountID,\
			pTradingAccount.PreMortgage,\
			pTradingAccount.PreCredit,\
			pTradingAccount.PreDeposit,\
			pTradingAccount.PreBalance,\
			pTradingAccount.PreMargin,\
			pTradingAccount.InterestBase,\
			pTradingAccount.Interest,\
			pTradingAccount.Deposit,\
			pTradingAccount.Withdraw,\
			pTradingAccount.FrozenMargin,\
			pTradingAccount.FrozenCash,\
			pTradingAccount.FrozenCommission,\
			pTradingAccount.CurrMargin,\
			pTradingAccount.CashIn,\
			pTradingAccount.Commission,\
			pTradingAccount.CloseProfit,\
			pTradingAccount.PositionProfit,\
			pTradingAccount.Balance,\
			pTradingAccount.Available,\
			pTradingAccount.WithdrawQuota,\
			pTradingAccount.Reserve,\
			pTradingAccount.TradingDay,\
			pTradingAccount.SettlementID,\
			pTradingAccount.Credit,\
			pTradingAccount.Mortgage,\
			pTradingAccount.ExchangeMargin,\
			pTradingAccount.DeliveryMargin,\
			pTradingAccount.ExchangeDeliveryMargin,\
			pTradingAccount.ReserveBalance,\
			pTradingAccount.CurrencyID,\
			pTradingAccount.PreFundMortgageIn,\
			pTradingAccount.PreFundMortgageOut,\
			pTradingAccount.FundMortgageIn,\
			pTradingAccount.FundMortgageOut,\
			pTradingAccount.FundMortgageAvailable,\
			pTradingAccount.MortgageableFund,\
			pTradingAccount.SpecProductMargin,\
			pTradingAccount.SpecProductFrozenMargin,\
			pTradingAccount.SpecProductCommission,\
			pTradingAccount.SpecProductFrozenCommission,\
			pTradingAccount.SpecProductPositionProfit,\
			pTradingAccount.SpecProductCloseProfit,\
			pTradingAccount.SpecProductPositionProfitByAlg,\
			pTradingAccount.SpecProductExchangeMargin,\
			pTradingAccount.BizType,\
			pTradingAccount.FrozenSwap,\
			pTradingAccount.RemainSwap,\
		]
		DealTooMax(currlist)
		self.myapi.ReqQryTraAccData.append(currlist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()


	def OnRspQryClassifiedInstrument(self, pInstrument: 'CThostFtdcInstrumentField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		currlist=[pInstrument.reserve1,\
			pInstrument.ExchangeID,\
			pInstrument.InstrumentName,\
			pInstrument.reserve2,\
			pInstrument.reserve3,\
			pInstrument.ProductClass,\
			pInstrument.DeliveryYear,\
			pInstrument.DeliveryMonth,\
			pInstrument.MaxMarketOrderVolume,\
			pInstrument.MinMarketOrderVolume,\
			pInstrument.MaxLimitOrderVolume,\
			pInstrument.MinLimitOrderVolume,\
			pInstrument.VolumeMultiple,\
			pInstrument.PriceTick,\
			pInstrument.CreateDate,\
			pInstrument.OpenDate,\
			pInstrument.ExpireDate,\
			pInstrument.StartDelivDate,\
			pInstrument.EndDelivDate,\
			pInstrument.InstLifePhase,\
			pInstrument.IsTrading,\
			pInstrument.PositionType,\
			pInstrument.PositionDateType,\
			pInstrument.LongMarginRatio,\
			pInstrument.ShortMarginRatio,\
			pInstrument.MaxMarginSideAlgorithm,\
			pInstrument.reserve4,\
			pInstrument.StrikePrice,\
			pInstrument.OptionsType,\
			pInstrument.UnderlyingMultiple,\
			pInstrument.CombinationType,\
			pInstrument.InstrumentID,\
			pInstrument.ExchangeInstID,\
			pInstrument.ProductID,\
			pInstrument.UnderlyingInstrID,\
		]
		DealTooMax(currlist)
		self.myapi.ReqQryClsInsData.append(currlist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()

	def OnRspQryInstrument(self, pInstrument: 'CThostFtdcInstrumentField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		currlist=[pInstrument.reserve1,\
			pInstrument.ExchangeID,\
			pInstrument.InstrumentName,\
			pInstrument.reserve2,\
			pInstrument.reserve3,\
			pInstrument.ProductClass,\
			pInstrument.DeliveryYear,\
			pInstrument.DeliveryMonth,\
			pInstrument.MaxMarketOrderVolume,\
			pInstrument.MinMarketOrderVolume,\
			pInstrument.MaxLimitOrderVolume,\
			pInstrument.MinLimitOrderVolume,\
			pInstrument.VolumeMultiple,\
			pInstrument.PriceTick,\
			pInstrument.CreateDate,\
			pInstrument.OpenDate,\
			pInstrument.ExpireDate,\
			pInstrument.StartDelivDate,\
			pInstrument.EndDelivDate,\
			pInstrument.InstLifePhase,\
			pInstrument.IsTrading,\
			pInstrument.PositionType,\
			pInstrument.PositionDateType,\
			pInstrument.LongMarginRatio,\
			pInstrument.ShortMarginRatio,\
			pInstrument.MaxMarginSideAlgorithm,\
			pInstrument.reserve4,\
			pInstrument.StrikePrice,\
			pInstrument.OptionsType,\
			pInstrument.UnderlyingMultiple,\
			pInstrument.CombinationType,\
			pInstrument.InstrumentID,\
			pInstrument.ExchangeInstID,\
			pInstrument.ProductID,\
			pInstrument.UnderlyingInstrID,\
		]
		DealTooMax(currlist)
		self.myapi.ReqQryInsData.append(currlist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()

	def OnRspQryInstrumentMarginRate(self, pInstrumentMarginRate: 'CThostFtdcInstrumentMarginRateField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		currlist=[pInstrumentMarginRate.reserve1,\
			pInstrumentMarginRate.InvestorRange,\
			pInstrumentMarginRate.BrokerID,\
			pInstrumentMarginRate.InvestorID,\
			pInstrumentMarginRate.HedgeFlag,\
			pInstrumentMarginRate.LongMarginRatioByMoney,\
			pInstrumentMarginRate.LongMarginRatioByVolume,\
			pInstrumentMarginRate.ShortMarginRatioByMoney,\
			pInstrumentMarginRate.ShortMarginRatioByVolume,\
			pInstrumentMarginRate.IsRelative,\
			pInstrumentMarginRate.ExchangeID,\
			pInstrumentMarginRate.InvestUnitID,\
			pInstrumentMarginRate.InstrumentID,\
		]
		DealTooMax(currlist)
		self.myapi.ReqQryInsMRData.append(currlist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()

	def OnRspQryInstrumentCommissionRate(self, pInstrumentCommissionRate: 'CThostFtdcInstrumentCommissionRateField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		currlist=[pInstrumentCommissionRate.reserve1,\
			pInstrumentCommissionRate.InvestorRange,\
			pInstrumentCommissionRate.BrokerID,\
			pInstrumentCommissionRate.InvestorID,\
			pInstrumentCommissionRate.OpenRatioByMoney,\
			pInstrumentCommissionRate.OpenRatioByVolume,\
			pInstrumentCommissionRate.CloseRatioByMoney,\
			pInstrumentCommissionRate.CloseRatioByVolume,\
			pInstrumentCommissionRate.CloseTodayRatioByMoney,\
			pInstrumentCommissionRate.CloseTodayRatioByVolume,\
			pInstrumentCommissionRate.ExchangeID,\
			pInstrumentCommissionRate.BizType,\
			pInstrumentCommissionRate.InvestUnitID,\
			pInstrumentCommissionRate.InstrumentID,\
		]
		DealTooMax(currlist)
		self.myapi.ReqQryInsCRData.append(currlist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()


	def OnRspQrySettlementInfo(self, pSettlementInfo: 'CThostFtdcSettlementInfoField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		#PrintReMsg(pRspInfo)
		currlist=[pSettlementInfo.SequenceNo,\
			pSettlementInfo.Content]
		self.myapi.ReqQrySettInfoData.append(currlist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()

	def OnRspQryDepthMarketData(self, pDepthMarketData: 'CThostFtdcDepthMarketDataField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		currlist = [pDepthMarketData.TradingDay,\
			pDepthMarketData.reserve1,\
			pDepthMarketData.ExchangeID,\
			pDepthMarketData.reserve2,\
			pDepthMarketData.LastPrice,\
			pDepthMarketData.PreSettlementPrice,\
			pDepthMarketData.PreClosePrice,\
			pDepthMarketData.PreOpenInterest,\
			pDepthMarketData.OpenPrice,\
			pDepthMarketData.HighestPrice,\
			pDepthMarketData.LowestPrice,\
			pDepthMarketData.Volume,\
			pDepthMarketData.Turnover,\
			pDepthMarketData.OpenInterest,\
			pDepthMarketData.ClosePrice,\
			pDepthMarketData.SettlementPrice,\
			pDepthMarketData.UpperLimitPrice,\
			pDepthMarketData.LowerLimitPrice,\
			pDepthMarketData.PreDelta,\
			pDepthMarketData.CurrDelta,\
			pDepthMarketData.UpdateTime,\
			pDepthMarketData.UpdateMillisec,\
			pDepthMarketData.BidPrice1,\
			pDepthMarketData.BidVolume1,\
			pDepthMarketData.AskPrice1,\
			pDepthMarketData.AskVolume1,\
			pDepthMarketData.BidPrice2,\
			pDepthMarketData.BidVolume2,\
			pDepthMarketData.AskPrice2,\
			pDepthMarketData.AskVolume2,\
			pDepthMarketData.BidPrice3,\
			pDepthMarketData.BidVolume3,\
			pDepthMarketData.AskPrice3,\
			pDepthMarketData.AskVolume3,\
			pDepthMarketData.BidPrice4,\
			pDepthMarketData.BidVolume4,\
			pDepthMarketData.AskPrice4,\
			pDepthMarketData.AskVolume4,\
			pDepthMarketData.BidPrice5,\
			pDepthMarketData.BidVolume5,\
			pDepthMarketData.AskPrice5,\
			pDepthMarketData.AskVolume5,\
			pDepthMarketData.AveragePrice,\
			pDepthMarketData.ActionDay,\
			pDepthMarketData.InstrumentID,\
			pDepthMarketData.ExchangeInstID,\
			pDepthMarketData.BandingUpperPrice,\
			pDepthMarketData.BandingLowerPrice,\
		]
		DealTooMax(currlist)
		self.myapi.ReqQryDepMarData.append(currlist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()

	def OnRspSettlementInfoConfirm(self, pSettlementInfoConfirm: 'CThostFtdcSettlementInfoConfirmField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		PrintReName("OnRspSettlementInfoConfirm")
		if(pRspInfo.ErrorID == 0):
			PrintReMsg(pRspInfo)
			self.myapi.ctlevent.set()
		else:
			PrintReMsg(pRspInfo)
			os._exit(233)

	def OnRtnInstrumentStatus(self, pInstrumentStatus: 'CThostFtdcInstrumentStatusField') -> "void":
		currdict=[{'ExchangeID': pInstrumentStatus.ExchangeID},\
			{'reserve1': pInstrumentStatus.reserve1 },\
			{'SettlementGroupID': pInstrumentStatus.SettlementGroupID },\
			{'reserve2': pInstrumentStatus.reserve2 },\
			{'InstrumentStatus': pInstrumentStatus.InstrumentStatus },\
			{'TradingSegmentSN': pInstrumentStatus.TradingSegmentSN },\
			{'EnterTime': pInstrumentStatus.EnterTime },\
			{'EnterReason': pInstrumentStatus.EnterReason },\
			{'ExchangeInstID': pInstrumentStatus.ExchangeInstID },\
			{'InstrumentID': pInstrumentStatus.InstrumentID },\
		]
		if(INSTRSTATUS == "1"):
			print(currdict)
#trade insert return
	def OnRspOrderInsert(self, pInputOrder: 'CThostFtdcInputOrderField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		PrintReName("OnRspOrderInsert")
		print ("InvestorID=", pInputOrder.InvestorID)
		print ("ErrorID=", pRspInfo.ErrorID, "ErrorMsg=", pRspInfo.ErrorMsg)


	def OnErrRtnOrderInsert(self, pInputOrder: 'CThostFtdcInputOrderField', pRspInfo: 'CThostFtdcRspInfoField') -> "void":
		PrintReName("OnErrRtnOrderInsert")
		print ("InvestorID=", pInputOrder.InvestorID)
		print ("ErrorMsg=", pRspInfo.ErrorMsg)

	def OnRtnOrder(self, pOrder: 'CThostFtdcOrderField' ) -> "void":
		PrintReName("OnRtnOrder")
		print ("investorid=", pOrder.InvestorID , "orderstatus=", pOrder.OrderStatus, "OrderSysID", pOrder.OrderSysID)
		print ("investorid=", pOrder.InvestorID , "ExchangeID=", pOrder.ExchangeID, "OrderSysID", pOrder.OrderSysID)
		print ("investorid=", pOrder.InvestorID , "IsAutoSuspend=", pOrder.IsAutoSuspend, "OrderSysID", pOrder.OrderSysID)
		print ("investorid=", pOrder.InvestorID , "OrderMemo=", pOrder.OrderMemo, "OrderSysID", pOrder.OrderSysID)
		self.myapi.exchangeid = pOrder.ExchangeID
		self.myapi.ordersysid = pOrder.OrderSysID

	def OnRtnTrade(self, pTrade: 'CThostFtdcTradeField' ) -> "void":
		PrintReName("OnRtnTrade")
		print ("investorid=", pTrade.InvestorID , "TradeID=", pTrade.TradeID, "OrderSysID", pTrade.OrderSysID)

#trade action return
	def OnRspOrderAction(self, pInputOrderAction: 'CThostFtdcInputOrderActionField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		PrintReName("OnRspOrderAction")
		print ("InvestorID=", pInputOrderAction.InvestorID)
		print ("ErrorID=", pRspInfo.ErrorID, "ErrorMsg=", pRspInfo.ErrorMsg)


	def OnErrRtnOrderAction(self, pOrderAction: 'CThostFtdcOrderActionField', pRspInfo: 'CThostFtdcRspInfoField') -> "void":
		PrintReName("OnErrRtnOrderAction")
		print ("InvestorID=", pOrderAction.InvestorID)
		print ("ErrorMsg=", pRspInfo.ErrorMsg)

#common error return
	def OnRspError(self, pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		PrintReName("OnRspOrderInsert")
		print ("ErrorID=", pRspInfo.ErrorID, "ErrorMsg=", pRspInfo.ErrorMsg)

#park order insert
	def OnRspParkedOrderInsert(self, pParkedOrder: 'CThostFtdcParkedOrderField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		PrintReName("OnRspParkedOrderInsert")
		print ("ErrorID=", pRspInfo.ErrorID, "ErrorMsg=", pRspInfo.ErrorMsg)

#Order Qry response
	def OnRspQryOrder(self, pOrder: 'CThostFtdcOrderField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		PrintReName("OnRspQryOrder")
		currdict = {'BrokerID': pOrder.BrokerID,\
			'InvestorID': pOrder.InvestorID,\
			'reserve1': pOrder.reserve1,\
			'OrderRef': pOrder.OrderRef,\
			'UserID': pOrder.UserID,\
			'OrderPriceType': pOrder.OrderPriceType,\
			'Direction': pOrder.Direction,\
			'CombOffsetFlag': pOrder.CombOffsetFlag,\
			'CombHedgeFlag': pOrder.CombHedgeFlag,\
			'LimitPrice': pOrder.LimitPrice,\
			'VolumeTotalOriginal': pOrder.VolumeTotalOriginal,\
			'TimeCondition': pOrder.TimeCondition,\
			'GTDDate': pOrder.GTDDate,\
			'VolumeCondition': pOrder.VolumeCondition,\
			'MinVolume': pOrder.MinVolume,\
			'ContingentCondition': pOrder.ContingentCondition,\
			'StopPrice': pOrder.StopPrice,\
			'ForceCloseReason': pOrder.ForceCloseReason,\
			'IsAutoSuspend': pOrder.IsAutoSuspend,\
			'BusinessUnit': pOrder.BusinessUnit,\
			'RequestID': pOrder.RequestID,\
			'OrderLocalID': pOrder.OrderLocalID,\
			'ExchangeID': pOrder.ExchangeID,\
			'ParticipantID': pOrder.ParticipantID,\
			'ClientID': pOrder.ClientID,\
			'reserve2': pOrder.reserve2,\
			'TraderID': pOrder.TraderID,\
			'InstallID': pOrder.InstallID,\
			'OrderSubmitStatus': pOrder.OrderSubmitStatus,\
			'NotifySequence': pOrder.NotifySequence,\
			'TradingDay': pOrder.TradingDay,\
			'SettlementID': pOrder.SettlementID,\
			'OrderSysID': pOrder.OrderSysID,\
			'OrderSource': pOrder.OrderSource,\
			'OrderStatus': pOrder.OrderStatus,\
			'OrderType': pOrder.OrderType,\
			'VolumeTraded': pOrder.VolumeTraded,\
			'VolumeTotal': pOrder.VolumeTotal,\
			'InsertDate': pOrder.InsertDate,\
			'InsertTime': pOrder.InsertTime,\
			'ActiveTime': pOrder.ActiveTime,\
			'SuspendTime': pOrder.SuspendTime,\
			'UpdateTime': pOrder.UpdateTime,\
			'CancelTime': pOrder.CancelTime,\
			'ActiveTraderID': pOrder.ActiveTraderID,\
			'ClearingPartID': pOrder.ClearingPartID,\
			'SequenceNo': pOrder.SequenceNo,\
			'FrontID': pOrder.FrontID,\
			'SessionID': pOrder.SessionID,\
			'UserProductInfo': pOrder.UserProductInfo,\
			'StatusMsg': pOrder.StatusMsg,\
			'UserForceClose': pOrder.UserForceClose,\
			'ActiveUserID': pOrder.ActiveUserID,\
			'BrokerOrderSeq': pOrder.BrokerOrderSeq,\
			'RelativeOrderSysID': pOrder.RelativeOrderSysID,\
			'ZCETotalTradedVolume': pOrder.ZCETotalTradedVolume,\
			'IsSwapOrder': pOrder.IsSwapOrder,\
			'BranchID': pOrder.BranchID,\
			'InvestUnitID': pOrder.InvestUnitID,\
			'AccountID': pOrder.AccountID,\
			'CurrencyID': pOrder.CurrencyID,\
			'reserve3': pOrder.reserve3,\
			'MacAddress': pOrder.MacAddress,\
			'InstrumentID': pOrder.InstrumentID,\
			'ExchangeInstID': pOrder.ExchangeInstID,\
			'IPAddress': pOrder.IPAddress,\
			'OrderMemo': pOrder.OrderMemo,\
			'SessionReqSeq': pOrder.SessionReqSeq}

		#print(currdict)
		self.myapi.ReqQryOrderData.append(currdict)
		if(bIsLast == True):
			print("Order info receive end")

#static function

#deal with too max float
def DealTooMax(mdlist):
	maxprice = 1e+15
	minprice = -1e+15
	for i in range(len(mdlist)):
		if((type(mdlist[i]) is not str) and (mdlist[i] > maxprice or mdlist[i] < minprice)):
			mdlist[i] = 0
		elif(type(mdlist[i]) is float):
			mdlist[i] = round(mdlist[i], 6)
		elif(mdlist[i] is None or mdlist[i] == ""):
			mdlist[i] = "NULL"
		else:
			mdlist[i] = mdlist[i]

#print errormsg
def PrintReMsg(pRspInfo):
	if pRspInfo is not None:
		remsg = "ErrorID= " + str(pRspInfo.ErrorID) + " ErrorMsg= " + str(pRspInfo.ErrorMsg)
		print(remsg)
	else:
		print("ErrorID= null ErrorMsg= null")
		return 1

#print func name
def PrintReName(rename):
	remsg = "receive" + rename
	print(remsg)